package utils

import (
	"errors"
	"github.com/golang-jwt/jwt/v4"
	"local.public/innerpkg/logger"
	"local.public/innerpkg/pubconfig"
	"strconv"
	"strings"
	"time"
)

//var (
//	ErrAbsent = "token absent" // 令牌不存在
//	ErrInvalid = "token invalid" // 令牌无效
//	ErrExpired = "token expired" // 令牌过期
//	ErrOther = "other error" // 其他错误
//)

type TokenOperator struct{}
type TokenParam struct {
	UserType       string
	UserId         string //内部id,为了方便，事先要转成字符串形式
	RoleIds        []int
	ManageStoreIds []int
	UserName       string //username
}

func (op *TokenOperator) GenToken(e *TokenParam) (string, error) {
	claims := jwt.MapClaims{
		"usertype": e.UserType,
		"userid":   e.UserId,
		"username": e.UserName,
		"roleids":  JoinIntArr(e.RoleIds, ","),
		"storeids": JoinIntArr(e.ManageStoreIds, ","),
		"exp":      time.Now().Add(time.Duration(pubconfig.GetConfig().Jwt.Timeout) * time.Second).Unix(), // 过期时间，必须设置,
	}

	token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
	tokenString, err := token.SignedString([]byte(pubconfig.GetConfig().Jwt.Key))
	if err != nil {
		logger.Debug("jwt签名错误" + err.Error())
	}
	return tokenString, err
}

func (op *TokenOperator) GenOneDayToken(e *TokenParam) (string, error) {
	claims := jwt.MapClaims{
		"usertype":   e.UserType,
		"userid":   e.UserId,
		"username": e.UserName,
		"roleids":  JoinIntArr(e.RoleIds, ","),
		"storeids": JoinIntArr(e.ManageStoreIds, ","),
		"exp":      time.Now().Add(86400 * time.Second).Unix(), // 过期时间，必须设置,
	}

	token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
	tokenString, err := token.SignedString([]byte(pubconfig.GetConfig().Jwt.Key))
	if err != nil {
		logger.Debug("jwt签名错误" + err.Error())
	}
	return tokenString, err
}

func (op *TokenOperator) ParseToken(tokenString string) (*TokenParam, error) {
	if tokenString == "" {
		err := errors.New("token is empty")
		logger.Debug("token is empty")
		return nil, err
	}
	sUserType := ""
	sUserId := ""
	sUserName := ""
	sRoleIds := ""
	sStoreIds := ""
	token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
		return []byte(pubconfig.GetConfig().Jwt.Key), nil
	})
	if err != nil {
		logger.Debug("parse token 失败！ err:" + err.Error())
		return nil, err
	}
	if !token.Valid {
		logger.Debug("token无效")
		return nil, errors.New("token无效")
	}
	//logger.Debug("token有效")
	claim, ok := token.Claims.(jwt.MapClaims)
	if !ok {
		logger.Debug("转为claim失败")
		return nil, errors.New("转为claim失败")
	}

	oUserType,okUserType := claim["usertype"]
	if okUserType {
		sUserType = oUserType.(string)
	} else {
		sUserType = ""
	}
	//sUserType= claim["usertype"].(string)
	sUserId = claim["userid"].(string)
	sUserName = claim["username"].(string)
	sRoleIds = claim["roleids"].(string)
	sStoreIds = claim["storeids"].(string)
	StrRoleIds := strings.Split(sRoleIds, ",")
	StrStoreIds := strings.Split(sStoreIds, ",")

	iRoleIds := make([]int, 0)
	for i := 0; i < len(StrRoleIds); i++ {
		iRoleId, _ := strconv.Atoi(StrRoleIds[i])
		iRoleIds = append(iRoleIds, iRoleId)
	}

	iStoreIds := make([]int, 0)
	for i := 0; i < len(StrStoreIds); i++ {
		iStoreId, _ := strconv.Atoi(StrStoreIds[i])
		iStoreIds = append(iStoreIds, iStoreId)
	}
	//sOperator = claim["operator"].(string)
	//iUserId, _ := strconv.Atoi(IfEmpty(sUserId, "0"))

	return &TokenParam{
		UserType:       sUserType,
		UserId:         sUserId,
		UserName:       sUserName,
		RoleIds:        iRoleIds,
		ManageStoreIds: iStoreIds,
	}, nil
}
